package com.zhou.core.cmd;

import com.alibaba.fastjson.JSON;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.jcraft.jsch.*;
import com.zhou.entitiy.ToolsResult;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

public class ShellCmd {
    private static final Logger log = LoggerFactory.getLogger(ShellCmd.class);

    private static final String ENCODING = "UTF-8";
    Session session;
    DestHost destHost;
    public ShellCmd(DestHost destHost)
    {
        this.destHost = destHost;
    }

    public void connect() throws JSchException {
        JSch jsch = new JSch();
        session = jsch.getSession(destHost.getUsername(), destHost.getHost(), destHost.getPort());
        session.setPassword(destHost.getPassword());

        session.setConfig("StrictHostKeyChecking", "no");  // 第一次访问服务器时不用输入yes
        session.setTimeout(destHost.getTimeout());
        session.connect();
        log.debug("ShellCmd connect host"+destHost.getHost()+",user="+destHost.getUsername()+" end... isConnected ={}",session.isConnected());
    }

    public ToolsResult execCommand(String command, String resultEncoding) throws IOException, JSchException {
        if (session == null || !session.isConnected())
        {
            connect();
        }
        return execCommand(session, command, resultEncoding);
    }

    public void disconnect() throws IOException, JSchException
    {
        log.debug("ShellCmd host={},user={} disconnect",destHost.getHost(),destHost.getUsername());
        if (session == null) return;
        session.disconnect();
    }

    /**
     * 执行命令,可以通过 ;分割多条命令
     * @param command
     * @return
     * @throws IOException
     * @throws JSchException
     */
    public ToolsResult execCommand(String command) throws IOException, JSchException {
        return execCommand(session, command, ENCODING);
    }

    public ToolsResult execCommand(Session session, String command, String resultEncoding) throws IOException, JSchException {
        log.debug("ShellCmd host={},user={},execCommand ={},resultEncoding={}  begin",destHost.getHost(),destHost.getUsername(),command,resultEncoding);
        ChannelExec channelExec = (ChannelExec) session.openChannel("exec");
        InputStream in = channelExec.getInputStream();
        channelExec.setCommand(command);
        channelExec.setErrStream(System.out);
        channelExec.connect();
        List<String> lineList = IOUtils.readLines(in, resultEncoding);
        String result = JSON.toJSONString(lineList);
        channelExec.disconnect();
        log.debug("ShellCmd host={},user={},execCommand ={},resultEncoding={},result={} end",destHost.getHost(),destHost.getUsername(),command,resultEncoding,result);
        return ToolsResult.createSuccResult(result);
    }

    /**
     * 目标登录主机信息
     */
    public static class DestHost {
        static final int DEFAULT_TIMEOUT = 3 * 60 * 1000;
        private String host = "";
        private String username = "";
        private String password = "";
        private int port = 22;
        private int timeout = DEFAULT_TIMEOUT;

        public DestHost(String host, String username, String password) {
            this(host, username, password, 22, DEFAULT_TIMEOUT);
        }

        public DestHost(String host, String username, String password, int timeout) {
            this(host, username, password, 22, timeout);
        }

        public DestHost(String host, String username, String password, int port, int timeout) {
            this.host = host;
            this.username = username;
            this.password = password;
            this.port = port;
            this.timeout = timeout;
        }

        public String getHost() {
            return host;
        }

        public void setHost(String host) {
            this.host = host;
        }

        public String getUsername() {
            return username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }

        public int getPort() {
            return port;
        }

        public void setPort(int port) {
            this.port = port;
        }

        public int getTimeout() {
            return timeout;
        }

        public void setTimeout(int timeout) {
            this.timeout = timeout;
        }

    }

    public static void main(String[] args) throws InterruptedException {
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(6, new ThreadFactoryBuilder().setNameFormat("cross-restart-%d").build());
        executor.execute(new Runnable() {
            @Override
            public void run() {
                //        DestHost host = new DestHost("122.51.10.61","root","lylove880927!@!@");
                DestHost host = new DestHost("52.8.73.147","red","FVbyRs28Gr");
                ShellCmd shellCmd = new ShellCmd(host);
                try {
                    shellCmd.connect();
                    String restartCmd = "bash /data/admin/war/7998_server/bin/restart.sh";
//            System.out.println(shellCmd.execCommand("pwd;cd /opt/app;pwd").getMsg());
                    System.out.println(shellCmd.execCommand(restartCmd).getMsg());
                }   catch (Exception e) {
                    e.printStackTrace();
                    log.error("",e);
                } finally {
                    try {
                        shellCmd.disconnect();
                    }catch (Exception e) {
                        log.error("",e);
                    }
                }
            }
        });


        Thread.sleep(1000000);


    }

   /* //远程主机的ip地址
    private String ip;
    //远程主机登录用户名
    private String username;
    //远程主机的登录密码
    private String password;
    //设置ssh连接的远程端口
    public static final int DEFAULT_SSH_PORT = 22;
    //保存输出内容的容器
    private ArrayList<String> stdout;

    *//**
     * 初始化登录信息
     * @param ip
     * @param username
     * @param password
     *//*
    public ShellCmd(final String ip, final String username, final String password) {
        this.ip = ip;
        this.username = username;
        this.password = password;
        stdout = new ArrayList<String>();
    }
    *//**
     * 执行shell命令
     * @param command
     * @return
     *//*
    public int execute(final String command) {
        int returnCode = 0;
        JSch jsch = new JSch();
        MyUserInfo userInfo = new MyUserInfo();

        try {
            //创建session并且打开连接，因为创建session之后要主动打开连接
            Session session = jsch.getSession(username, ip, DEFAULT_SSH_PORT);
            session.setPassword(password);
            session.setUserInfo(userInfo);
            session.connect();

            //打开通道，设置通道类型，和执行的命令
            Channel channel = session.openChannel("exec");
            ChannelExec channelExec = (ChannelExec)channel;
            channelExec.setCommand(command);

            channelExec.setInputStream(null);
            BufferedReader input = new BufferedReader(new InputStreamReader
                    (channelExec.getInputStream()));

            channelExec.connect();
            System.out.println("The remote command is :" + command);

            String out = IOUtils.toString(channelExec.getInputStream(), "UTF-8");
            //接收远程服务器执行命令的结果
            String line;
            while ((line = input.readLine()) != null) {
                stdout.add(line);
            }
            input.close();

            // 得到returnCode
            if (channelExec.isClosed()) {
                returnCode = channelExec.getExitStatus();
            }

            // 关闭通道
            channelExec.disconnect();
            //关闭session
            session.disconnect();

        } catch (JSchException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return returnCode;
    }
    *//**
     * get stdout
     * @return
     *//*
    public ArrayList<String> getStandardOutput() {
        return stdout;
    }*/

}
